function Game(canvas)
{
    "use strict";
    this.canvas = canvas;
    var graphics = canvas.getContext("2d");
    var sceneStack = [];
    this.activeScene = null;
    this.addScene = function (id, frameRate)
    {
        var scene = new Scene(id, graphics, this.canvas, frameRate);
        sceneStack.push(scene);
        return scene;
    };

    this.startGame = function ()
    {
        if (sceneStack.length > 0)
        {
            sceneStack[0].startScene();
            sceneStack[0].activateEventListeners();
            this.activeScene = sceneStack[0];
        }
    };

    this.pauseGame = function ()
    {
        this.activeScene.pauseScene();
        this.activeScene.pauseSound();
        this.activeScene.deactivateEventListeners();
    };
    this.resumeGame = function ()
    {
        this.activeScene.startScene();
        this.activeScene.resumeSound();
        this.activeScene.activateEventListeners();
    };
    this.pauseSound = function ()
    {
        this.activeScene.pauseSound();
    };
    this.resumeSound = function ()
    {
        this.activeScene.resumeSound();
    };
    this.nextScene = function ()
    {
        var id = this.activeScene.id;
        var index = -1;
        for (var i = 0; i < sceneStack.length; i++)
        {
            if (sceneStack[i].id === id)
                index = i;
        }
        if (index !== -1 && index !== (sceneStack.length - 1))
        {
            var audioState = this.activeScene.getAudioState();
            this.activeScene.pauseScene();
            this.activeScene.pauseSound();
            this.activeScene.deactivateEventListeners();
            sceneStack[index + 1].setAudioState(audioState);
            sceneStack[index + 1].startScene();
            sceneStack[index + 1].activateEventListeners();
            this.activeScene = sceneStack[index + 1];
        }
        else
        {
            window.console.log("scene not found or last scene on the stack is already active");
        }
    };
    this.skipToScene = function (sceneId)
    {
        this.activeScene.pauseScene();
        this.activeScene.pauseSound();
        this.activeScene.deactivateEventListeners();
        var newScene = this.getSceneById(sceneId);
        newScene.startScene();
        newScene.activateEventListeners();
        this.activeScene = newScene;
    };

    this.getSceneById = function (id)
    {
        for (var i = 0; i < sceneStack.length; i++)
        {
            if (sceneStack[i].id === id)
                return sceneStack[i];
        }
        return null;
    };
}
function Scene(id, graphics, canvas, frameRate)
{
    "use strict";
    var drawStack = [];
    var soundStack = [];
    var audioStack = [];
    this.id = id;
    this.graphics = graphics;
    var audioPaused = false;
    var WIDTH = canvas.width;
    var HEIGHT = canvas.height;
    var interval = 1000 / frameRate;
    var renderer = null;

    this.getAudioState = function ()
    {
        return audioPaused;
    };
    this.setAudioState = function (audioState)
    {
        audioPaused = audioState;
    };
    this.getDrawStack = function ()
    {
        return drawStack;
    };
    this.startScene = function ()
    {
        canvas.focus();
        renderer = setInterval(this.renderDrawStack, interval);
    };

    this.pauseScene = function ()
    {
        if (renderer !== null)
        {
            clearInterval(renderer);
        }
    };

    this.scheduleSound = function (object, path, loop)
    {
        if (object in soundStack)
            soundStack[object].push(new Sound(path, loop));
        else
        {
            soundStack[object] = [];
            soundStack[object].push(new Sound(path, loop));
        }
    };
    var playSound = function (object)
    {
        if (!audioPaused)
        {
            if (object in soundStack)
            {
                if (soundStack[object].length > 0)
                {
                    for (var i = 0; i < soundStack[object].length; i++)
                    {
                        var soundObj = soundStack[object].pop();
                        var audio = new Audio(soundObj.path);
                        if (soundObj.loop === true)
                        {
                            audio.addEventListener("ended", resetSong);
                        }
                        audioStack.push(audio);
                        audio.play();
                    }
                }
            }
        }
    };
    var resetSong = function ()
    {
        this.currentTime = 0;
        this.play();
    };
    this.pauseSound = function ()
    {
        if (audioStack.length > 0)
        {
            for (var i = 0; i < audioStack.length; i++)
                audioStack[i].pause();
        }
        audioPaused = true;
    };
    this.resumeSound = function ()
    {
        if (audioStack.length > 0)
        {
            for (var i = 0; i < audioStack.length; i++)
            {
                if (audioStack[i].currentTime > 0 && audioStack[i].currentTime < audioStack[i].duration)
                {
                    audioStack[i].play();
                }
            }
        }
        audioPaused = false;
    };
    this.destroyScene = function ()
    {
        if (renderer !== null)
            clearInterval(renderer);
        drawStack.length = 0;
        soundStack.length = 0;
        audioStack.length = 0;
        graphics.clearRect(0, 0, WIDTH, HEIGHT);
    };

    this.clearScene = function ()
    {
        drawStack.length = 0;
    };
    this.registerEventHandler = function (id, type, func)
    {
        var object = this.getObjectById(id);
        object.registerEventHandler(type, func);
    };
    this.activateEventListeners = function ()
    {
        canvas.onclick = function (event)
        {
            var posX = event.pageX - canvas.offsetLeft;
            var posY = event.pageY - canvas.offsetTop;
            for (var i = 0; i < drawStack.length; i++)
            {
                var tmp = drawStack[i];
                if (tmp.click !== undefined && tmp.click !== null)
                    tmp.click(posX, posY, event);
            }
        };

        canvas.onmousemove = function (event)
        {
            var posX = event.pageX - canvas.offsetLeft;
            var posY = event.pageY - canvas.offsetTop;
            for (var i = 0; i < drawStack.length; i++)
            {
                var tmp = drawStack[i];
                if (tmp.mouseOver !== undefined && tmp.mouseOver !== null)
                    tmp.mouseOver(posX, posY, event);
                if (tmp.mouseOut !== undefined && tmp.mouseOut !== null)
                    tmp.mouseOut(posX, posY);
            }
        };

        window.onkeydown = function (event)
        {
            for (var i = 0; i < drawStack.length; i++)
            {
                if (drawStack[i].keyDown !== undefined && drawStack[i].keyDown !== null)
                    drawStack[i].keyDown(event);
            }
        };
        window.onkeyup = function (event)
        {
            for (var i = 0; i < drawStack.length; i++)
            {
                if (drawStack[i].keyUp !== undefined && drawStack[i].keyUp !== null)
                    drawStack[i].keyUp(event);
            }
        };
    };
    this.deactivateEventListeners = function ()
    {
        canvas.onclick = null;
        canvas.onmouseover = null;
        canvas.onmousemove = null;
        canvas.onmouseout = null;
        canvas.onkeydown = null;
        canvas.onkeyUp = null;
    };

    this.getObjectById = function (id)
    {
        var index = -1;
        for (var i = 0; i < drawStack.length; i++)
        {
            if (drawStack[i].id === id)
                index = i;
        }
        if (index !== -1)
            return drawStack[index];
        else
            return null;
    };

    this.getAllObjectsById = function (id)
    {
        var objects = [];
        for (var i = 0; i < drawStack.length; i++)
        {
            if (drawStack[i].id === id)
                objects.push(drawStack[i]);
        }
        return objects;
    };

    this.getObjectIndex = function (id)
    {
        for (var i = 0; i < drawStack.length; i++)
        {
            if (drawStack[i].id === id)
                return i;
        }
        return -1;
    };

    this.getAllObjectIndices = function (id)
    {
        var indices = [];
        for (var i = 0; i < drawStack.length; i++)
        {
            if (drawStack[i].id === id)
                indices.push(i);
        }
        return indices;
    };
    this.deleteObject = function (index)
    {
        drawStack.splice(index, 1);
    };

    this.deleteAllObjects = function (id)
    {
        var objects = this.getAllObjectIndices(id);
        var len = objects.length;
        for (var i = 0; i < len; i++)
        {
            var tmpObjects = this.getAllObjectIndices(id);
            if (tmpObjects.length > 0)
                drawStack.splice(tmpObjects[0], 1);
        }
    };
    this.createText = function (text, id, color, font, initialAlpha, alphaIncrement, posX, posY, fill, stroke, animateX, animateY, waitForFade, typeEffect, maxWidth, callback)
    {
        var stringLen = text.length;
        var letterWidth = parseInt(font.substring(0, 2), 10) / 2;
        var currentChar = 0;
        var currentX = posX;
        var currentY = posY;
        if (typeEffect)
        {
            var listenForSpace = false;
            for (; currentChar < stringLen; currentChar++)
            {
                var tmpChar = text.charAt(currentChar);
                if (listenForSpace && tmpChar === ' ')
                {
                    currentX = posX;
                    currentY += (letterWidth * 2);
                    listenForSpace = false;
                    continue;
                }
                else if (listenForSpace && tmpChar !== ' ')
                {
                        currentX += letterWidth;
                }
                drawStack.push(new CustomText(tmpChar, id, color, font, initialAlpha, alphaIncrement, currentX, currentY, fill, stroke, animateX, animateY, waitForFade));
                if (currentX >= (posX + maxWidth))
                {
                    listenForSpace = true;
                }
                else
                    currentX += letterWidth;
            }
        }
        else
        {
            drawStack.push(new CustomText(text, id, color, font, initialAlpha, alphaIncrement, posX, posY, fill, stroke, animateX, animateY, waitForFade));
        }
        if (callback !== undefined && callback !== null)
            callback();
    };


    this.loadImage = function (path, id, initialAlpha, alphaIncrement, srcX, srcY, srcWidth, srcHeight, dstX, dstY, dstWidth, dstHeight, cursor, animateX, animateY, bindToFrame, volatile, callback)
    {
        var image = new Image();
        image.onload = function ()
        {
            drawStack.push(new CustomImage(image, id, initialAlpha, alphaIncrement, srcX, srcY, srcWidth, srcHeight, dstX, dstY, dstWidth, dstHeight, cursor, animateX, animateY, bindToFrame, volatile));
            if (callback !== undefined)
                callback();
        };
        image.src = path;
    };


    this.createCircle = function (id, color, initialAlpha, alphaIncrement, posX, posY, scaleX, scaleY, radius, startAngle, endAngle, fill, stroke, animateX, animateY, waitForFade, antiClockwise, callback)
    {
        drawStack.push(new Circle(id, color, initialAlpha, alphaIncrement, posX, posY, scaleX, scaleY, radius, startAngle, endAngle, fill, stroke, animateX, animateY, waitForFade, antiClockwise));
        if (callback !== undefined && callback !== null)
            callback();
    };

    this.createRect = function (id, color, initialAlpha, alphaIncrement, posX, posY, width, height, fill, stroke, cursor, animateX, animateY, waitForFade, afterPush)
    {
        drawStack.push(new Rectangle(id, color, initialAlpha, alphaIncrement, posX, posY, width, height, fill, stroke, cursor, animateX, animateY, waitForFade));
        if (afterPush !== undefined && afterPush !== null)
            afterPush();
    };


    this.renderDrawStack = function renderDrawStack()
    {
        if (drawStack.length === 0)
            graphics.clearRect(0, 0, canvas.width, canvas.height);
        else
        {
            graphics.clearRect(0, 0, canvas.width, canvas.height);
            for (var i = 0; i < drawStack.length; i++)
            {
                var tmp = drawStack[i];
                playSound(tmp.id);
                if (tmp.collision !== undefined && tmp.collision !== null)
                    detectCollision(i, tmp, drawStack);
                if (!tmp.render(i, drawStack, graphics, canvas))
                    break;
            }
        }
        canvas.title = "Particles on the drawing stack: " + drawStack.length;
    };
}

function detectCollision(index, image, objects)
{
    "use strict";
    for (var i = 0; i < objects.length; i++)
    {
        var tmp = objects[i];
        if (tmp.id.indexOf(image.id) === -1 && tmp.id !== "background")
        {
            if (tmp instanceof CustomImage)
            {
                if ((image.dstX + image.dstWidth >= tmp.dstX &&
                    image.dstX + image.dstWidth <= tmp.dstX + tmp.dstWidth &&
                    image.dstY + image.dstHeight >= tmp.dstY &&
                    image.dstY + image.dstHeight <= tmp.dstY + tmp.dstHeight) ||
                    (tmp.dstX + tmp.dstWidth >= image.dstX &&
                        tmp.dstX + tmp.dstWidth <= image.dstX + image.dstWidth &&
                        tmp.dstY + tmp.dstHeight >= image.dstY &&
                        tmp.dstY + tmp.dstHeight <= image.dstY + image.dstHeight)
                    )
                {
                    image.collision(i, tmp, index, image);
                }
            }
        }
    }
}
function CustomImage(image, id, initialAlpha, alphaIncrement, srcX, srcY, srcWidth, srcHeight, dstX, dstY, dstWidth, dstHeight, cursor, animateX, animateY, bindToFrame, volatile)
{
    "use strict";
    this.image = image;
    this.id = id;
    this.initialAlpha = initialAlpha;
    this.alphaIncrement = alphaIncrement;
    this.srcX = srcX;
    this.srcY = srcY;
    this.srcWidth = srcWidth !== -1 ? srcWidth : this.image.width;
    this.srcHeight = srcHeight !== -1 ? srcHeight : this.image.height;
    this.dstX = dstX;
    this.dstY = dstY;
    this.dstWidth = dstWidth !== -1 ? dstWidth : this.image.width;
    this.dstHeight = dstHeight !== -1 ? dstHeight : this.image.height;
    this.cursor = cursor;
    this.animateX = animateX;
    this.animateY = animateY;
    this.bindToFrame = bindToFrame;
    this.volatile = volatile;
    this.mouseOver = function (posX, posY, event)
    {
        if (posX > this.dstX && posX < (this.dstX + this.dstWidth) && posY > this.dstY && posY < (this.dstY + this.dstHeight))
        {
            event.target.style.cursor = this.cursor;
        }
    };
    this.mouseOut = null;
    this.click = null;
    this.keyDown = null;
    this.keyUp = null;
    this.collision = null;
    this.registerEventHandler = function (type, func)
    {
        switch (type)
        {
            case "onmouseover":
                this.mouseOver = function (posX, posY, event)
                {
                    if (posX > this.dstX && posX < (this.dstX + this.dstWidth) && posY > this.dstY && posY < (this.dstY + this.dstHeight))
                    {
                        event.target.style.cursor = this.cursor;
                        func();
                    }
                };
                break;
            case "onmouseout":
                this.mouseOut = function (posX, posY)
                {
                    if (!(posX > this.dstX && posX < (this.dstX + this.dstWidth) && posY > this.dstY && posY < (this.dstY + this.dstHeight)))
                    {
                        func();
                    }
                };
                break;
            case "onclick":
                this.click = function (posX, posY)
                {
                    if (posX > this.dstX && posX < (this.dstX + this.dstWidth) && posY > this.dstY && posY < (this.dstY + this.dstHeight))
                        func();
                };
                break;
            case "onkeydown":
                this.keyDown = function (event)
                {
                    func(event);
                };
                break;
            case "onkeyup":
                this.keyUp = function (event)
                {
                    func(event);
                };
                break;
            case "oncollision":
                this.collision = function (collidedIndex, collidedWith, thisIndex, thisObject)
                {
                    func(collidedIndex, collidedWith, thisIndex, thisObject);
                };
                break;
        }
    };

    this.render = function (index, drawStack, graphics, canvas)
    {
        graphics.save();
        if (this.initialAlpha >= 1 && this.alphaIncrement >= 0)
            graphics.globalAlpha = 1;
        else if (this.initialAlpha > 1 && this.alphaIncrement < 0)
        {
            this.initialAlpha = 1;
            graphics.globalAlpha = this.initialAlpha;
            this.initialAlpha += this.alphaIncrement;
        }
        else if (this.initialAlpha <= 0 && this.alphaIncrement <= 0)
            graphics.globalAlpha = 0;
        else if (this.initialAlpha < 0 && this.alphaIncrement > 0)
        {
            this.initialAlpha = 0;
            graphics.globalAlpha = this.initialAlpha;
            this.initialAlpha += this.alphaIncrement;
        }
        else
        {
            graphics.globalAlpha = this.initialAlpha;
            this.initialAlpha += this.alphaIncrement;
        }
        graphics.drawImage(this.image, this.srcX, this.srcY, this.srcWidth, this.srcHeight, this.dstX, this.dstY, this.dstWidth, this.dstHeight);
        if (this.bindToFrame)
        {
            if ((this.dstX + this.dstWidth + this.animateX) > canvas.width || (this.dstX + this.animateX) < 0)
                this.animateX = -this.animateX;
            if ((this.dstY + this.dstHeight + this.animateY) > canvas.height || (this.dstY + this.animateY) < 0)
                this.animateY = -this.animateY;
        }
        this.dstX += this.animateX;
        this.dstY += this.animateY;
        if (this.volatile)
        {
            if (this.dstX > canvas.width || this.dstX < 0 || this.dstY > canvas.height || this.dstY < 0 || (this.initialAlpha <= 0 && this.alphaIncrement <= 0))
                drawStack.splice(index, 1);
        }
        graphics.restore();
        return true;
    };
}
function Sound(path, loop)
{
    "use strict";
    this.path = path;
    this.loop = loop;
}

function Circle(id, color, initialAlpha, alphaIncrement, posX, posY, scaleX, scaleY, radius, startAngle, endAngle, fill, stroke, animateX, animateY, waitForFade, antiClockwise)
{
    "use strict";
    this.id = id;
    this.color = color;
    this.initialAlpha = initialAlpha;
    this.alphaIncrement = alphaIncrement;
    this.posX = posX;
    this.posY = posY;
    this.scaleX = scaleX;
    this.scaleY = scaleY;
    this.radius = radius;
    this.startAngle = startAngle;
    this.endAngle = endAngle;
    this.antiClockwise = antiClockwise;
    this.fill = fill;
    this.stroke = stroke;
    this.animateX = animateX;
    this.animateY = animateY;
    this.waitForFade = waitForFade;
    this.keyDown = null;
    this.keyUp = null;
    this.registerEventHandler = function (type, func)
    {
        switch (type)
        {
            case "onkeydown":
                this.keyDown = func;
                break;
            case "onkeyup":
                this.keyUp = func;
                break;
        }
    };
    this.render = function (index, drawStack, graphics, canvas)
    {
        graphics.save();
        graphics.beginPath();
        if (this.initialAlpha >= 1 && this.alphaIncrement >= 0)
            graphics.globalAlpha = 1;
        else if (this.initialAlpha > 1 && this.alphaIncrement < 0)
        {
            this.initialAlpha = 1;
            graphics.globalAlpha = this.initialAlpha;
            this.initialAlpha += this.alphaIncrement;
        }
        else if (this.initialAlpha <= 0 && this.alphaIncrement <= 0)
            graphics.globalAlpha = 0;
        else if (this.initialAlpha < 0 && this.alphaIncrement > 0)
        {
            this.initialAlpha = 0;
            graphics.globalAlpha = this.initialAlpha;
            this.initialAlpha += this.alphaIncrement;
        }
        else
        {
            graphics.globalAlpha = this.initialAlpha;
            this.initialAlpha += this.alphaIncrement;
        }
        graphics.fillStyle = this.color;
        graphics.scale(this.scaleX, this.scaleY);
        graphics.arc(this.posX, this.posY, this.radius, this.startAngle, this.endAngle, this.antiClockwise);
        if (this.fill)
            graphics.fill();
        if (this.stroke)
            graphics.stroke();
        if (this.animateX !== 0 || this.animateY !== 0)
        {
            if ((this.posX + this.radius + this.animateX) > canvas.width || (this.posX - this.radius + this.animateX) < 0)
                this.animateX = -this.animateX;
            if ((this.posY + this.radius + this.animateY) > canvas.height || (this.posY - this.radius + this.animateY) < 0)
                this.animateY = -this.animateY;
            this.posX += this.animateX;
            this.posY += this.animateY;
        }
        graphics.closePath();
        graphics.restore();
        if (this.waitForFade)
        {
            if (this.initialAlpha < 1 && this.initialAlpha > 0)
                return false;
        }
        return true;
    };
}

function Rectangle(id, color, initialAlpha, alphaIncrement, posX, posY, width, height, fill, stroke, cursor, animateX, animateY, waitForFade)
{
    "use strict";
    this.id = id;
    this.color = color;
    this.initialAlpha = initialAlpha;
    this.alphaIncrement = alphaIncrement;
    this.posX = posX;
    this.posY = posY;
    this.width = width;
    this.height = height;
    this.fill = fill;
    this.stroke = stroke;
    this.cursor = cursor;
    this.animateX = animateX;
    this.animateY = animateY;
    this.waitForFade = waitForFade;
    this.mouseOver = function (posX, posY, event)
    {
        if (posX > this.posX && posX < (this.posX + this.width) && posY > this.posY && posY < (this.posY + this.height))
            event.target.style.cursor = this.cursor;
    };
    this.click = null;
    this.keyDown = null;
    this.keyUp = null;
    this.registerEventHandler = function (type, func)
    {
        switch (type)
        {
            case "onmouseover":
                this.mouseOver = function (posX, posY, event)
                {
                    if (posX > this.posX && posX < (this.posX + this.width) && posY > this.posY && posY < (this.posY + this.height))
                    {
                        event.target.style.cursor = this.cursor;
                        func();
                    }
                };
                break;
            case "onclick":
                this.click = function (posX, posY)
                {
                    if (posX > this.posX && posX < (this.posX + this.width) && posY > this.posY && posY < (this.posY + this.height))
                        func();
                };
                break;
            case "onkeydown":
                this.keyDown = func;
                break;
            case "onkeyup":
                this.keyUp = func;
                break;
        }
    };
    this.render = function (index, drawStack, graphics, canvas)
    {
        graphics.save();
        graphics.beginPath();
        graphics.fillStyle = this.color;
        if (this.initialAlpha >= 1 && this.alphaIncrement >= 0)
            graphics.globalAlpha = 1;
        else if (this.initialAlpha > 1 && this.alphaIncrement < 0)
        {
            this.initialAlpha = 1;
            graphics.globalAlpha = this.initialAlpha;
            this.initialAlpha += this.alphaIncrement;
        }
        else if (this.initialAlpha <= 0 && this.alphaIncrement <= 0)
            graphics.globalAlpha = 0;
        else if (this.initialAlpha < 0 && this.alphaIncrement > 0)
        {
            this.initialAlpha = 0;
            graphics.globalAlpha = this.initialAlpha;
            this.initialAlpha += this.alphaIncrement;
        }
        else
        {
            graphics.globalAlpha = this.initialAlpha;
            this.initialAlpha += this.alphaIncrement;
        }
        if (this.fill)
            graphics.fillRect(this.posX, this.posY, this.width, this.height);
        if (this.stroke)
            graphics.strokeRect(this.posX, this.posY, this.width, this.height);
        if (this.animateX !== 0 || this.animateY !== 0)
        {
            if (this.posX + this.width + this.animateX > canvas.width || this.posX + this.animateX < 0)
                this.animateX = -this.animateX;
            if (this.posY + this.height + this.animateY > canvas.height || this.posY + this.animateY < 0)
                this.animateY = -this.animateY;
            this.posX += this.animateX;
            this.posY += this.animateY;
        }
        graphics.closePath();
        graphics.restore();
        if (this.waitForFade)
        {
            if (this.initialAlpha < 1 && this.initialAlpha > 0)
                return false;
        }
        return true;
    };
}

function CustomText(text, id, color, font, initialAlpha, alphaIncrement, posX, posY, fill, stroke, animateX, animateY, waitForFade)
{
    "use strict";
    this.text = text;
    this.id = id;
    this.color = color;
    this.font = font;
    this.initialAlpha = initialAlpha;
    this.alphaIncrement = alphaIncrement;
    this.posX = posX;
    this.posY = posY;
    this.width = parseInt(font.substring(0, 2), 10);
    this.fill = fill;
    this.stroke = stroke;
    this.animateX = animateX;
    this.animateY = animateY;
    this.waitForFade = waitForFade;
    this.render = function (index, drawStack, graphics, canvas)
    {
        graphics.save();
        graphics.beginPath();
        graphics.fillStyle = this.color;
        graphics.font = this.font;
        if (this.initialAlpha >= 1 && this.alphaIncrement >= 0)
            graphics.globalAlpha = 1;
        else if (this.initialAlpha > 1 && this.alphaIncrement < 0)
        {
            this.initialAlpha = 1;
            graphics.globalAlpha = this.initialAlpha;
            this.initialAlpha += this.alphaIncrement;
        }
        else if (this.initialAlpha <= 0 && this.alphaIncrement <= 0)
            graphics.globalAlpha = 0;
        else if (this.initialAlpha < 0 && this.alphaIncrement > 0)
        {
            this.initialAlpha = 0;
            graphics.globalAlpha = this.initialAlpha;
            this.initialAlpha += this.alphaIncrement;
        }
        else
        {
            graphics.globalAlpha = this.initialAlpha;
            this.initialAlpha += this.alphaIncrement;
        }
        if (this.fill)
            graphics.fillText(this.text, this.posX, this.posY);
        if (this.stroke)
            graphics.strokeText(this.text, this.posX, this.posY);
        if (this.animateX !== 0 || this.animateY !== 0)
        {
            if ((this.posX + this.width + this.animateX) > canvas.width || (this.posX + this.animateX) < 0)
                this.animateX = -this.animateX;
            if ((this.posY + this.width + this.animateY) > canvas.height || (this.posY + this.animateY) < 0)
                this.animateY = -this.animateY;
            this.posX += this.animateX;
            this.posY += this.animateY;
        }
        graphics.closePath();
        graphics.restore();
        if (this.waitForFade)
        {
            if (this.initialAlpha < 1 && this.initialAlpha > 0)
                return false;
        }
        return true;
    };
}